#ifndef SIMP_H
#define SIMP_H


class EdgeHeapKey 
{
public :
	EdgeHeapKey (Edge * e)
	{
		//ehk.first = e->he->from_v->idx; 
		//ehk.second = e->he->next->from_v->idx; 
		//cost = e->cost ;
		edge = e;
	}
	friend bool operator < (const EdgeHeapKey & lhs, const EdgeHeapKey & rhs)
	{
		//return (lhs.cost < rhs.cost);
		return lhs.edge->cost < rhs.edge->cost ;
	}
	friend std::ostream & operator << (std::ostream & ostr, const EdgeHeapKey & key)
	{
		//ostr << '('<<key.ehk.first<<','<<key.ehk.second<<')' <<':' << key.cost<<' '; 
		return ostr; 
	}
public :
	EdgeHashKey ehk;
	double cost;
	Edge * edge ;
};

class Heap
{
public:
	Edge * pop ()
	{
		std::multiset <EdgeHeapKey >::iterator iter = heap.begin();
		Edge * e = iter->edge ;
		heap.erase(iter);
		return e;
	}

	void insert (Edge * e)
	{
		edge_iterators[edgeHashKey(e)] = heap.insert(EdgeHeapKey(e));
	}
	void remove (EdgeHashKey ehk)
	{
		heap.erase(edge_iterators[ehk]); 
		edge_iterators.erase(ehk); 
	}
	size_t size() const
	{
		return (heap.size()) ;
	}
	void update (Edge * e)
	{
		remove(edgeHashKey(e));
		insert(e);
	}
	bool empty() const 
	{
		return (heap.size() == 0);
	}

	void print_heap()
	{
		
		std::cout<<"Heap Size"<<heap.size()<<std::endl;
		std::multiset<EdgeHeapKey>::iterator iter = heap.begin() ;
		for (;
			iter != heap.end(); ++iter)
		{
			std::cout<<iter->edge <<' '<< iter->cost<<' '; 
		}
		std::cout<<std::endl;
		
	}
	void print_hash ()
	{

	}
private:
	std::multiset <EdgeHeapKey > heap;
	stdext::hash_map <EdgeHashKey, std::multiset <EdgeHeapKey >::iterator> edge_iterators;
};


class Heap_naive
{
public:
	Edge * pop ()
	{
		stdext::hash_map <EdgeHashKey, Edge *  >::iterator pos = heap.begin();
		stdext::hash_map <EdgeHashKey, Edge *  >::iterator iter = heap.begin() ;
		++iter; 
		for (;
			iter != heap.end(); ++iter)
		{
			//std::cout<<pos->second->cost <<','<< iter->second->cost<<"Hello"<<std::endl;
			if (pos->second->cost > iter->second->cost)
			{
				pos = iter; 
			}
		}
		//std::cout<<"Lease Value"<<pos->second->cost; 
		Edge * e = pos->second ;
		heap.erase(pos); 
		return e ;
	}

	void insert (Edge * e)
	{
		heap[edgeHashKey(e)] = e; 
	}
	void remove (EdgeHashKey ehk)
	{
		heap.erase(ehk);
	}
	void remove (Edge * e)
	{
		heap.erase(edgeHashKey(e));
	}
	size_t size() const
	{
		return (heap.size()) ;
	}
	bool empty() const 
	{
		return (heap.size() == 0);
	}
	void update(Edge * )
	{
	}
	void print_heap()
	{
		std::cout<<"Heap Size"<<heap.size()<<std::endl;
		stdext::hash_map <EdgeHashKey, Edge *  >::iterator iter = heap.begin() ;
		for (;
			iter != heap.end(); ++iter)
		{
			std::cout<<iter->second <<' '<<iter->second->cost<<' ';
		}
		std::cout<<std::endl;
	}
	void print_hash ()
	{

	}
private:
	stdext::hash_map <HashKey, Edge * > heap;
};
void simplification (Mesh & mesh, unsigned num_collapse) ;
#endif